package com.oceantrader.sale.biz.staff.controller;

import java.util.List;

import org.springframework.stereotype.Component;

import com.oceantrader.sale.biz.staff.entity.Staff;
import com.oceantrader.sale.biz.staff.pojo.StaffSearchParam;
import com.oceantrader.sale.biz.staff.service.StaffService;
import com.oceantrader.sale.commons.config.api.ApiResult;
import com.oceantrader.sale.commons.config.api.BackendApiAuth;
import com.oceantrader.sale.commons.config.exceptions.ParamException;
import com.oceantrader.sale.commons.config.exceptions.ServiceException;
import com.oceantrader.sale.commons.pojo.PageResult;
import com.oceantrader.sale.constant.BackendApiContext;
import com.xuesinuo.xtool.Np;

import io.vertx.core.Future;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.Router;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@RequiredArgsConstructor
public class StaffController {
    private final Router router;
    private final StaffService staffService;
    private final BackendApiAuth backendApiAuth;

    /** 新增员工 */
    @PostConstruct
    public void addStaff() {
        router.route(HttpMethod.POST, "/backend/staff/addStaff").handler(http -> {
            Staff param = http.body().asPojo(Staff.class);
            param.setId(null);
            if (param.getCode() == null || param.getCode().isBlank()) {
                throw new ParamException("编号不能为空");
            }
            if (param.getNick() == null || param.getNick().isBlank()) {
                throw new ParamException("称呼不能为空");
            }
            if (param.getPhone() == null || param.getPhone().isBlank()) {
                throw new ParamException("电话不能为空");
            }
            if (param.getUsername() == null || param.getPhone().isBlank()) {
                throw new ParamException("用户名不能为空");
            }
            if (param.getPassword() == null || param.getPhone().isBlank()) {
                throw new ParamException("密码不能为空");
            }
            param.setCreateDatetime(null);
            param.setCreateStaffId(http.get(BackendApiContext.STAFF_ID));
            if (param.getAdmin() == null) {
                param.setAdmin(false);
            }
            if (param.getEnable() == null) {
                param.setEnable(false);
            }
            staffService.addStaff(param)
                    .onSuccess(newId -> {
                        http.response().write(ApiResult.ok());
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    @Data
    public static class DelStaffParam {
        private List<Long> idList;
    }

    /** 删除员工 */
    @PostConstruct
    public void delStaff() {
        router.route(HttpMethod.POST, "/backend/staff/delStaff").handler(http -> {
            DelStaffParam param = http.body().asPojo(DelStaffParam.class);
            if (param.getIdList() == null || param.getIdList().isEmpty()) {
                throw new ParamException("ID不能为空");
            }
            staffService.delStaff(param.getIdList())
                    .onSuccess(row -> {
                        http.response().write(ApiResult.ok());
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    @Data
    public class SetStaffParam {
        /** ID */
        private Long id;
        /** 称呼 */
        private String nick;
        /** 电话号 */
        private String phone;
        /** 密码 */
        private String password;
        /** 是否启用 */
        private Boolean enable;
    }

    /** 修改员工信息 */
    @PostConstruct
    public void setStaff() {
        router.route(HttpMethod.POST, "/backend/staff/setStaff").handler(http -> {
            SetStaffParam param = http.body().asPojo(SetStaffParam.class);
            if (param.getId() == null) {
                throw new ParamException("ID不能为空");
            }
            if (param.getNick() == null || param.getPhone() == null || param.getPassword() == null || param.getEnable() == null) {
                throw new ParamException("缺少要修改的内容");
            }
            Staff updater = new Staff();
            updater.setId(param.getId());
            updater.setNick(param.getNick());
            updater.setPhone(param.getPhone());
            updater.setPassword(param.getPassword());
            updater.setEnable(param.getEnable());
            staffService.setStaff(updater)
                    .onSuccess(row -> {
                        http.response().write(ApiResult.ok());
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    /** 员工列表 */
    @PostConstruct
    public void getStaffPage() {
        router.route(HttpMethod.GET, "/backend/staff/getStaffPage").handler(http -> {
            StaffSearchParam param = new StaffSearchParam();
            param.putMultiMap(http.request().params());
            Future<List<Staff>> staffListFuture = staffService.getStaff(param);
            Future<Long> staffCountFuture = staffService.getStaffCount(param);
            Future.all(staffListFuture, staffCountFuture)
                    .onSuccess(listAndCount -> {
                        List<Staff> staffList = listAndCount.resultAt(0);
                        Long count = listAndCount.resultAt(1);
                        http.response().write(ApiResult.ok(new PageResult<>(count, staffList)));
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    @Data
    public static class SigninParam {
        private String username;
        private String password;
    }

    @Data
    @AllArgsConstructor
    public static class SigninResult {
        private String token;
    }

    /** 登录 */
    @PostConstruct
    public void signin() {
        router.route(HttpMethod.POST, "/backend/staff/signin").handler(http -> {
            SigninParam param = http.body().asPojo(SigninParam.class);
            if (param.getUsername() == null || param.getPassword() == null) {
                throw new ParamException("用户名或密码不能为空");
            }
            staffService.getStaffByUsername(param.getUsername())
                    .onSuccess(staff -> {
                        if (Np.i(staff).x(x -> x.getPassword()).notEq(param.getPassword())) {
                            http.fail(new ServiceException("用户名或密码错误"));
                            return;
                        }
                        backendApiAuth.signin(staff.getId())
                                .onSuccess(token -> {
                                    http.response().write(ApiResult.ok(new SigninResult(token)));
                                    http.next();
                                })
                                .onFailure(e -> http.fail(e));
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    /** 登出 */
    @PostConstruct
    public void signout() {
        router.route(HttpMethod.POST, "/backend/staff/signout").handler(http -> {
            String token = http.get(BackendApiContext.TOKEN);
            if (token == null) {
                http.response().write(ApiResult.ok());
                http.next();
            }
            backendApiAuth.signout(token)
                    .onSuccess(v -> {
                        http.response().write(ApiResult.ok());
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    /** 我的个人信息 */
    @PostConstruct
    public void my() {
        router.route(HttpMethod.GET, "/backend/staff/my").handler(http -> {
            Long userId = http.get(BackendApiContext.STAFF_ID);
            staffService.getStaffById(userId)
                    .onSuccess(staff -> {
                        http.response().write(ApiResult.ok(staff));
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    @Data
    public static class ResetMyPasswordParam {
        private String oldPassword;
        private String newPassword;
    }

    /** 修改我的密码 */
    @PostConstruct
    public void resetMyPassword() {
        router.route(HttpMethod.POST, "/backend/staff/resetMyPassword").handler(http -> {
            Long userId = http.get(BackendApiContext.STAFF_ID);
            ResetMyPasswordParam param = http.body().asPojo(ResetMyPasswordParam.class);
            if (param.getOldPassword() == null || param.getNewPassword() == null) {
                throw new ParamException("旧密码或新密码不能为空");
            }
            staffService.getStaffPasswordById(userId)
                    .onSuccess(oldPassword -> {
                        if (Np.i(oldPassword).eq(param.getOldPassword())) {
                            Staff updater = new Staff();
                            updater.setId(userId);
                            updater.setPassword(param.getNewPassword());
                            staffService.setStaff(updater).onSuccess(row -> {
                                http.response().write(ApiResult.ok());
                                http.next();
                            }).onFailure(e -> {
                                http.fail(e);
                            });
                        } else {
                            http.fail(new ServiceException("旧密码错误"));
                        }
                    })
                    .onFailure(e -> http.fail(e));
        });
    }

    @Data
    public static class SetMyParam {
        /** 称呼 */
        private String nick;
        /** 电话号 */
        private String phone;
    }

    /** 修改我的个人信息 */
    @PostConstruct
    public void setMy() {
        router.route(HttpMethod.POST, "/backend/staff/setMy").handler(http -> {
            SetMyParam param = http.body().asPojo(SetMyParam.class);
            if (param.getNick() == null || param.getPhone() == null) {
                throw new ParamException("缺少要修改的内容");
            }
            Staff updater = new Staff();
            updater.setId(http.get(BackendApiContext.STAFF_ID));
            updater.setNick(param.getNick());
            updater.setPhone(param.getPhone());
            staffService.setStaff(updater)
                    .onSuccess(row -> {
                        http.response().write(ApiResult.ok());
                        http.next();
                    })
                    .onFailure(e -> http.fail(e));
        });
    }
}
